package org.asiainfo.flowable.controller;

import cn.hutool.core.util.ObjectUtil;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.RequiredArgsConstructor;
import org.asiainfo.common.core.domain.R;
import org.asiainfo.common.web.core.BaseController;
import org.asiainfo.flowable.domain.bo.WfTaskBo;
import org.asiainfo.flowable.service.WfTaskService;
import org.asiainfo.flowable.utils.WfTaskUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * 工作流任务管理
 *
 * @author dotor-ww
 */
@RestController
@RequiredArgsConstructor
@Validated
@RequestMapping("/wfTask")
public class WfTaskController extends BaseController {

    private final WfTaskService wfTaskService;

    /**
     * 审批任务
     *
     * @param wfTaskBo 流程任务业务对象
     * @return 审批结果
     */
    @PostMapping("/complete")
    public R<Void> completeTask(@RequestBody WfTaskBo wfTaskBo) {
        wfTaskService.completeTask(wfTaskBo);
        return R.ok();
    }

    /**
     * 驳回任务
     *
     * @param wfTaskBo 流程任务业务对象
     * @return 驳回结果
     */
    @PostMapping("/reject")
    public R<Void> rejectTask(@RequestBody WfTaskBo wfTaskBo) {
        wfTaskService.rejectTask(wfTaskBo);
        return R.ok();
    }

    /**
     * 退回任务
     *
     * @param wfTaskBo 流程任务业务对象
     * @return 退回结果
     */
    @PostMapping("/return")
    public R<Void> returnTask(@RequestBody WfTaskBo wfTaskBo) {
        wfTaskService.returnTask(wfTaskBo);
        return R.ok();
    }

    /**
     * 删除任务
     *
     * @param wfTaskBo 流程任务业务对象
     * @return 删除结果
     */
    @DeleteMapping("/delete")
    public R<Void> deleteTask(@RequestBody WfTaskBo wfTaskBo) {
        wfTaskService.deleteTask(wfTaskBo);
        return R.ok();
    }

    /**
     * 取消申请
     *
     * @param wfTaskBo 流程任务业务对象
     * @return 取消结果
     */
    @PostMapping("/stopProcess")
    public R<Void> stopProcess(@RequestBody WfTaskBo wfTaskBo) {
        wfTaskService.stopProcess(wfTaskBo);
        return R.ok();
    }

    /**
     * 获取任务变量
     *
     * @param taskId 任务ID
     * @return 任务变量
     */
    @GetMapping("/processVariables/{taskId}")
    public R<Object> processVariables(@NotEmpty(message = "任务ID不能为空") @PathVariable("taskId") String taskId) {
        return R.ok(wfTaskService.processVariables(taskId));
    }

    /**
     * 获取所有可回退节点
     *
     * @param wfTaskBo 流程任务业务对象
     * @return 回退节点
     */
    @PostMapping("/returnList")
    public R<Object> findReturnList(@RequestBody WfTaskBo wfTaskBo) {
        return R.ok(wfTaskService.findReturnTaskList(wfTaskBo));
    }

    /**
     * 认领、签收任务
     *
     * @param wfTaskBo 流程任务业务对象
     * @return 认领、签收结果
     */
    @PostMapping("/claim")
    public R<Void> claim(@RequestBody WfTaskBo wfTaskBo) {
        wfTaskService.claim(wfTaskBo);
        return R.ok();
    }

    /**
     * 取消认领、签收任务
     *
     * @param wfTaskBo 流程任务业务对象
     * @return 认领、签收结果
     */
    @PostMapping("/unClaim")
    public R<Void> unClaim(@RequestBody WfTaskBo wfTaskBo) {
        wfTaskService.unClaim(wfTaskBo);
        return R.ok();
    }

    /**
     * 委派任务
     *
     * @param wfTaskBo 流程任务业务对象
     * @return 委派结果
     */
    @PostMapping("/delegate")
    public R<Void> delegate(@RequestBody WfTaskBo wfTaskBo) {
        if (ObjectUtil.hasNull(wfTaskBo.getTaskId(), WfTaskUtils.getUserId())) {
            return R.fail("任务ID和委托人不能为空");
        }
        wfTaskService.delegate(wfTaskBo);
        return R.ok();
    }

    /**
     * 转办任务
     *
     * @param wfTaskBo 流程任务业务对象
     * @return 转办结果
     */
    @PostMapping("/transfer")
    public R<Void> transfer(@RequestBody WfTaskBo wfTaskBo) {
        if (ObjectUtil.hasNull(wfTaskBo.getTaskId(), WfTaskUtils.getUserId())) {
            return R.fail("任务ID和委托人不能为空");
        }
        wfTaskService.transfer(wfTaskBo);
        return R.ok();
    }

    /**
     * 撤回流程
     *
     * @param wfTaskBo 流程任务业务对象
     * @return 撤回结果
     */
    @PostMapping("/revokeProcess")
    public R<Void> revokeProcess(@RequestBody WfTaskBo wfTaskBo) {
        wfTaskService.revokeProcess(wfTaskBo);
        return R.ok();
    }

    /**
     * 获取流程图
     *
     * @param processId 流程实例ID
     * @param response  响应
     */
    @GetMapping("/diagram/{processId}")
    public void genProcessDiagram(@NotBlank(message = "流程ID不能为空") @PathVariable("processId") String processId, HttpServletResponse response) {
        // try-with-resources语句来自动关闭流
        try (InputStream inputStream = wfTaskService.diagram(processId);
             OutputStream os = response.getOutputStream()) {
            BufferedImage image = ImageIO.read(inputStream);
            if (ObjectUtil.isNotNull(image)) {
                response.setContentType("image/png");
                ImageIO.write(image, "png", os);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
